package com.woonoz.network.windows;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

import com.woonoz.network.AdvancedProxySelector;
import com.woonoz.network.InvalidPacException;
import com.woonoz.network.NetworkLogger;
import com.woonoz.network.PacInterpreterException;

public class WindowsProxySelector extends ProxySelector {

	private final ProxySelector selector;
	
	public WindowsProxySelector() {
		final InputStream pacInputStream = getPacInputStream();

		NetworkLogger.LOGGER.info("instanciate windows proxy selector");
		
		ProxySelector advSelector = null;
		if (pacInputStream != null) {
			try {
				advSelector = new AdvancedProxySelector(pacInputStream);				
			} catch (PacInterpreterException e) {
				NetworkLogger.LOGGER.error("", e);
			} catch (InvalidPacException e) {
				NetworkLogger.LOGGER.error("", e);
			} catch (IOException e) {
				NetworkLogger.LOGGER.error("", e);
			}
		}
		if (advSelector == null) {
			selector = ProxySelector.getDefault();
			NetworkLogger.LOGGER.info("using default proxy selector");
		} else {
			selector = advSelector;
			NetworkLogger.LOGGER.info("using pac interpretor as proxy selector");
		}
	}
	
	private InputStream getPacInputStream() {
		try {
			final WindowsRegistryReader reader = new WindowsRegistryReader();
			final String pacUrlString = reader.readUserKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "AutoConfigURL");
			if (pacUrlString != null) {
				final URL pacUrl = new URL(pacUrlString);
				final URLConnection connection = pacUrl.openConnection(Proxy.NO_PROXY);
				final InputStream pacInputStream = connection.getInputStream();
				return pacInputStream;
			}
		} catch (IOException e) {
			NetworkLogger.LOGGER.error("", e);
		} catch (SecurityException e) {
			NetworkLogger.LOGGER.error("", e);
		} catch (NoSuchMethodException e) {
			NetworkLogger.LOGGER.error("", e);
		} catch (IllegalArgumentException e) {
			NetworkLogger.LOGGER.error("", e);
		} catch (IllegalAccessException e) {
			NetworkLogger.LOGGER.error("", e);
		} catch (InvocationTargetException e) {
			NetworkLogger.LOGGER.error("", e);
		}
		return null;
	}
	
	@Override
	public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
		selector.connectFailed(uri, sa, ioe);
	}

	@Override
	public List<Proxy> select(URI uri) {
		return selector.select(uri);
	}

}
